home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / dskut / pdisk.zip / RDPART.C < prev    next >
C/C++ Source or Header  |  1989-01-12  |  7KB  |  268 lines

  1. #include "part.h"
  2. #include <bios.h>
  3. #include <dos.h>
  4. #include <malloc.h>
  5. #include <errno.h>
  6.  
  7. BOOT *master_boot_rec,        /* master boot record of currently selected disk */
  8.      *part_boot_rec[4];        /* boot record of each (active) logical partition */
  9.  
  10. static word start_mode, start_page;
  11. byte changed_parms;                /* if this byte is set, save_tbl (below) has
  12.                                  * a ptr to the original (BIOS or whatever)
  13.                                  * disk table, and must be reset.
  14.                                  */
  15. DISK_TABLE far *fd_tbl,
  16.                far *save_tbl;
  17.  
  18. byte num_disks,
  19.      fixed_disk,
  20.      _numsecs;
  21. word _shprod;
  22. extern word sector_size;
  23. PARTDATA part_data[4];
  24. extern int dotrans(dword relsect,word startsec,void *buf,word numsec,word op);
  25.  
  26. void
  27. init()        /* initialize tables from a given physical disk */
  28. {
  29.     static byte _init = 0;
  30.     static word old_sector_size = 0;
  31.     struct diskinfo_t diskinfo;
  32.     int i;
  33.  
  34.     /* if first time through, fill num_disks */
  35.     if(! _init) {
  36.         _init = 1;
  37.         diskinfo.drive = fixed_disk;
  38.         _bios_disk(8,&diskinfo);
  39.         if((num_disks = diskinfo.drive) == 0) {
  40.             fprintf(stderr,"No fixed disks attached.\n");
  41.             exit(1);
  42.             /* NOTREACHED */
  43.         }
  44.         if(num_disks==1 && fixed_disk==DISK1) {
  45.             fprintf(stderr,"Only one disk attached.\n");
  46.             exit(2);
  47.             /* NOTREACHED */
  48.         }
  49.         start_page = scr_gapage();
  50.         scr_sapage(0);
  51.         start_mode = scr_gmode();
  52.         switch(start_mode) {
  53.         case 0:
  54.         case 5:
  55.         case 6:
  56.             scr_smode(2);
  57.             break;
  58.         case 1:
  59.         case 4:
  60.             scr_smode(3);
  61.             break;
  62.         }
  63.         master_boot_rec = (BOOT *)malloc(sector_size);
  64.         for(i=0;i<4;i++)
  65.             part_boot_rec[i] = (BOOT *)malloc(sector_size);
  66.     }
  67.     else {
  68.         if(old_sector_size != sector_size) {
  69.             master_boot_rec = (BOOT *)realloc(master_boot_rec,sector_size);
  70.             for(i=0; i<4; i++)
  71.                 part_boot_rec[i] = (BOOT *)realloc(part_boot_rec[i],sector_size);
  72.         }
  73.         if(changed_parms) {
  74.             /* we cast the table vector as a pointer to a far interrupt handler
  75.              * function returning void, since that is what _dos_setvect expects.
  76.              */
  77.             _dos_setvect(changed_parms==DISK1 ? 0x46 : 0x41,
  78.                          (void (interrupt far *)()) save_tbl
  79.                         );
  80.             diskinfo.drive = changed_parms;
  81.             _bios_disk(0x09, &diskinfo);        /* reset drive pair vector */
  82.             diskinfo.drive = changed_parms;
  83.             _bios_disk(0, &diskinfo);        /* reset drive */
  84.             changed_parms = 0;
  85.         }
  86.     }
  87.  
  88.     old_sector_size = sector_size;
  89.     fd_tbl = (DISK_TABLE far *) _dos_getvect(fixed_disk==DISK1 ? 0x46 : 0x41);
  90.     _numsecs = fd_tbl->fd_sec_per_track;
  91.     _shprod = _numsecs * fd_tbl->fd_heads;
  92.     boot_transfer(READ,0);
  93.     for(i=0; i<4; i++) {
  94.         if((part_data[i].sys_ind = master_boot_rec->ptable[i].sys_ind) != 0) {
  95.              part_data[i].s_cylinder=get_cyl(master_boot_rec->ptable[i].s_sec_cyl);
  96.             part_data[i].e_cylinder=get_cyl(master_boot_rec->ptable[i].e_sec_cyl);
  97.             boot_transfer(READ,i+1);
  98.         }
  99.     }
  100. }
  101.  
  102. void
  103. clean_quit()
  104. {
  105.     struct diskinfo_t diskinfo;
  106.  
  107.     if(changed_parms) {
  108.         _dos_setvect(changed_parms==DISK1 ? 0x46 : 0x41,
  109.                      (void (interrupt far *)())  save_tbl
  110.                     );
  111.         diskinfo.drive = changed_parms;
  112.         _bios_disk(0x09, &diskinfo);        /* reset drive pair vector */
  113.         diskinfo.drive = changed_parms;
  114.         _bios_disk(0, &diskinfo);        /* reset drive */
  115.         changed_parms = 0;
  116.     }
  117.     scr_sapage(start_page);
  118.     scr_smode(start_mode);
  119.     exit(0);
  120.     /* NOTREACHED */
  121. }
  122.  
  123. int
  124. make_fat(partno, fat_size, secs_in_rdir)    /* make FAT (two copies) */
  125. int partno,
  126.     fat_size;
  127. word secs_in_rdir;
  128. {
  129.     int i;
  130.     word *fatbuf, numsecs, offset, data_offset, secs_per_clus, secs_in_part;
  131.     byte *fatbuf2, *scratch;
  132.     BPB *bptr = &part_boot_rec[partno]->bpb;
  133.     dword relsec = master_boot_rec->ptable[partno].rel_sect;
  134.     extern word lineno;
  135.  
  136.     numsecs = bptr->secs_in_fat;
  137.     data_offset = numsecs*2 + secs_in_rdir + bptr->res_sectors;
  138.     secs_in_part = bptr->nsectors;
  139.     secs_per_clus = (word) bptr->secs_per_au;
  140.     scratch = malloc(sector_size*secs_per_clus);
  141. #ifdef DEBUG
  142.     printf("numsecs %d, offset %d, part_size %d\n",numsecs,data_offset,secs_in_part);
  143.     fflush(stdout);
  144. #endif
  145.     if(!(fatbuf = (word *)calloc(numsecs,sector_size))) {
  146.         errno = ENOMEM;
  147.         return(0);
  148.         /* NOTREACHED */
  149.     }
  150.     fatbuf2 = (byte *)fatbuf;
  151.     if(fat_size == 12) {
  152.         fatbuf[0] = 0xfff8;
  153.         fatbuf[1] = 0x00ff;
  154.     }
  155.     else {
  156.         fatbuf[0] = 0xfff8;
  157.         fatbuf[1] = 0xffff;
  158.     }
  159.     /* get a list of sectors that can't be read -- presumably result of lo
  160.      * level formatting.  Mark off appropriate cluster as bad.
  161.      */
  162. #ifndef DEBUG
  163.     scr_pos(lineno,42);
  164.     printf("Sector:");
  165.     for(offset=data_offset; offset <= secs_in_part; offset += secs_per_clus) {
  166.         word i;
  167.  
  168.         i = (offset+secs_per_clus <= secs_in_part) ? secs_per_clus :
  169.                                                      (secs_in_part-offset+1);
  170.         scr_pos(lineno,50);
  171.         printf("%u",offset-data_offset);
  172.         fflush(stdout);
  173.         if(dotrans(relsec,offset,scratch, i, READ)) {
  174.             /* got a bad sector */
  175.             word cnum = (offset - data_offset)/secs_per_clus + 2;
  176.  
  177.             if(fat_size == 12) {
  178.                 /* byte offset into cluster array is cnum*3/2 */
  179.                 word *cptr = (word *)(fatbuf2 + ((cnum*3) >> 1));
  180.                 
  181.                 *cptr  |= (cnum & 1) ? 0xff70 : 0xff7;
  182.             }
  183.             else
  184.                 fatbuf[cnum] = 0xfff7;
  185.         }
  186.     }
  187. #endif
  188.     for(i=0; i<2; i++)
  189. #ifndef DEBUG
  190.         if(dotrans(relsec,(i*numsecs)+1,fatbuf,numsecs,WRITE) < 0) {
  191.             errno = EINVAL;
  192.             return(0);
  193.             /* NOTREACHED */
  194.         }
  195. #else
  196.         printf("Writing FAT, relsec 0x%lxL, whither 0x%x, count %d\n",
  197.                 relsec,(i*numsecs)+1,numsecs);
  198.     fflush(stdout); (void) getch();
  199. #endif
  200.     free(scratch);
  201.     free(fatbuf);
  202.     return(numsecs);
  203. }
  204.  
  205. int
  206. make_rdir(partno)    /* make the root directory */
  207. int partno;
  208. {
  209.     int numsecs, offset;
  210.     word *buf, csize, temp;
  211.     BPB *bptr = &part_boot_rec[partno]->bpb;
  212.     dword relsec = master_boot_rec->ptable[partno].rel_sect;
  213.  
  214.     offset = (bptr->secs_in_fat << 1) + 1;
  215.     numsecs = (bptr->nroot_ents+15)/16;
  216.     csize = (word) bptr->secs_per_au;
  217.     if((temp = numsecs % csize) != 0)
  218.             numsecs += csize-temp;
  219.     if((buf = (word *)calloc(numsecs,sector_size)) == NULL) {
  220.         errno = ENOMEM;
  221.         return(0);
  222.         /* NOTREACHED */
  223.     }
  224. #ifndef DEBUG
  225.     if(dotrans(relsec,offset,buf,numsecs, WRITE) < 0) {
  226.         errno = EINVAL;
  227.         return(0);
  228.         /* NOTREACHED */
  229.     }
  230. #else
  231.     printf("Writing directory, relsec (long) 0x%lx, whither 0x%x, count %d\n", relsec,offset,numsecs);
  232.     fflush(stdout); getch();
  233. #endif
  234.     free(buf);
  235.     return(numsecs);
  236. }
  237.  
  238. #ifdef BT_IN_C
  239. void
  240. boot_transfer(op, idx)
  241. word op,    /* either READ or WRITE */
  242.      idx;    /* 0=master boot record, 1-5=partition */
  243. {
  244.     union REGS fregs;
  245.     struct SREGS segreg;
  246.  
  247.     if(idx) {
  248.         PARTITION *pptr;
  249.  
  250.         pptr = & master_boot_rec->ptable[--idx];
  251.         fregs.x.bx = (unsigned) part_boot_rec[idx];
  252.         segreg.es = FP_SEG(part_boot_rec[idx]);
  253.         fregs.x.cx = pptr->s_sec_cyl;        /* cylinder 0, sector 1 */
  254.         fregs.h.dh = pptr->s_head;            /* head 0 */
  255.     }
  256.     else {
  257.         fregs.x.bx = (unsigned) master_boot_rec;
  258.         segreg.es = FP_SEG(master_boot_rec);
  259.         fregs.x.cx = 0x0001;        /* cylinder 0, sector 1 */
  260.         fregs.h.dh = 0;                /* head 0 */
  261.     }
  262.     fregs.h.ah = op;    /* what to do */
  263.     fregs.h.al = 1;        /* do 1 sector */
  264.     fregs.h.dl = fixed_disk;
  265.     int86x(0x13,&fregs,&fregs,&segreg);
  266. }
  267. #endif
  268.